import { Injectable, Optional } from '@angular/core';
import { NotifyService } from '@farris/ui-notify';
import { TreeNode } from '@farris/ui-treetable';
import { FormBasicService, FormBinding, FormBindingType, FormVariable, DesignerEnvType, FormSchema, DesignViewModelService, DomService, SchemaService, } from '@farris/designer-services';
import { Observable, of, Subject } from 'rxjs';
import { cloneDeep } from 'lodash-es';
import { FarrisMetadataService } from '@farris/designer-services';

const ROOT_VIEW_MODEL_ID = 'root-viewmodel';
/**
 * 选择映射的组件参数
 */
export class SelectMappingEditorParam {
  /** 源表单的id */
  public sourceMetadataId: string;

  /** 源表单类型，默认为'help'（帮助） */
  public sourceMetadataType: string;

  /** 源表单展示标题，默认为'帮助' */
  public sourceMetadataName: string;

  /** 源表单字段列表 */
  public sourceMappingFields: TreeNode[];

  /** 控件所属视图模型id */
  public viewModelId: string;

  /** 控件绑定信息 */
  public binding: any;

  public helpId: string;

  /** 是否多选 */
  public isMultiSelect: boolean;
}

@Injectable()
export class MappingFieldManager {

  constructor(
    private formBasicServ: FormBasicService, private domService: DomService,
    private schemaService: SchemaService,
    private dgVMService: DesignViewModelService, private notifyService: NotifyService,
    @Optional() private unifiedMetadataService: FarrisMetadataService
  ) { }

  /**
   * 组装源字段树表数据
   * @param editorParams 编辑器参数
   */
  public assembleSourceFields(editorParams: SelectMappingEditorParam) {
    if (editorParams.sourceMappingFields) {
      const sourceFields = this.getStaticSourceMappingFields(cloneDeep(editorParams.sourceMappingFields)) || [];
      return of(sourceFields);
    } else {
      return this.getSoruceMetadata(editorParams);
    }
  }

  /**
   * 静态数据源补充bindingPath属性
   * @param sourceMappingFields 数据源
   * @returns 数据源
   */
  private getStaticSourceMappingFields(sourceMappingFields: TreeNode[]) {
    sourceMappingFields.forEach(f => {
      if (!f.data.bindingPath) {
        f.data.bindingPath = f.data.label;
      }
    });

    return sourceMappingFields;
  }
  /**
   * 根据源元数据id获取元数据字段
   * @param editorParams 编辑器参数
   */
  private getSoruceMetadata(editorParams: SelectMappingEditorParam): Subject<TreeNode[]> {
    if (!editorParams.sourceMetadataId) {
      return;
    }
    const subject = new Subject<TreeNode[]>();

    const ob = this.unifiedMetadataService.getMetadata(editorParams.sourceMetadataId);;

    if (ob) {
      const sourceMetadataType = editorParams.sourceMetadataType || 'help';
      ob.subscribe(helpData => {
        switch (sourceMetadataType) {
          case 'help': {
            const helpMetadataContent = JSON.parse(helpData.content);
            if (helpMetadataContent && helpMetadataContent.schema && helpMetadataContent.schema.main) {
              const fields = this.resolveSourceFields(helpMetadataContent.schema.main);
              subject.next(fields);
            }
            break;
          }
          case 'form': {
            let frmContent = JSON.parse(helpData.content).Contents;
            if (typeof (frmContent) === 'string') {
              frmContent = JSON.parse(frmContent);
            }
            const fields = this.resolveSourceFields(frmContent.module.schemas[0]);
            subject.next(fields);
            break;
          }
        }

      }, () => {
        this.notifyService.error('获取元数据失败！');
      });
    }
    return subject;

  }

  /**
   * 获取帮助schema字段
   * @param schema schema
   */
  private resolveSourceFields(schema: FormSchema) {
    if (!schema || !schema.entities || schema.entities.length === 0) {
      return [];
    }
    const mainTable = schema.entities[0];
    if (mainTable.type && mainTable.type.fields) {
      return this.schemaService.assembleFields2Tree(mainTable.type.fields);
    }

  }

  /**
   * 获取表单列或变量信息
   */
  assembleTargetFields(binding: FormBinding, viewModelId: string) {
    if (!binding || !viewModelId) {
      return;
    }
    if (binding.type === FormBindingType.Form) {
      return this.dgVMService.getAllFields2TreeByVMId(viewModelId);
    } else if (binding.type === FormBindingType.Variable) {
      const varialbeViewModelId = binding.path.includes('.') ? ROOT_VIEW_MODEL_ID : viewModelId;
      const variable = this.domService.getVariableByIdAndVMID(binding.field, varialbeViewModelId);

      const varTree = this.assembleVariable2Tree(cloneDeep(variable));
      return [varTree];
    }
  }

  private assembleVariable2Tree(variable: FormVariable, bindingPath = '') {
    // 补充bindingPath属性
    if (!variable['bindingPath']) {
      variable['bindingPath'] = (bindingPath ? bindingPath + '.' : '') + variable.code;
    }
    const children = [];
    if (variable.fields && variable.fields.length > 0) {
      variable.fields.forEach(v => {
        const child = this.assembleVariable2Tree(v, variable['bindingPath']);
        children.push(child);
      });
    }
    return {
      data: { ...variable, label: variable.code },
      children,
      selectable: children.length > 0 ? false : true,
      expanded: true,
    };


  }
}
